package com.stylefeng.guns.modular.vpn_channel_action_info.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.stylefeng.guns.core.common.constant.DatasourceEnum;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.mutidatasource.annotion.DataSource;
import com.stylefeng.guns.core.util.DateUtil;
import com.stylefeng.guns.modular.system.model.VpnChannelActionInfo;
import com.stylefeng.guns.modular.system.dao.VpnChannelActionInfoMapper;
import com.stylefeng.guns.modular.system.model.VpnChannelInfo;
import com.stylefeng.guns.modular.vpn.bo.ChannelLineBO;
import com.stylefeng.guns.modular.vpn.dto.ChannelActionDTO;
import com.stylefeng.guns.modular.vpn.entity.*;
import com.stylefeng.guns.modular.vpn.utils.PoiExcelUtil;
import com.stylefeng.guns.modular.vpn.utils.TimeUtil;
import com.stylefeng.guns.modular.vpn.vo.Paging;
import com.stylefeng.guns.modular.vpn_channel_action_info.service.IVpnChannelActionInfoService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.modular.vpn_channel_info.service.IVpnChannelInfoService;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author godrui
 * @since 2020-06-05
 */
@Service
public class VpnChannelActionInfoServiceImpl extends ServiceImpl<VpnChannelActionInfoMapper, VpnChannelActionInfo> implements IVpnChannelActionInfoService {

    @Resource
    private IVpnChannelInfoService vpnChannelInfoService;

    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public Object list(ChannelActionDTO dto) {
        Paging<ChannelActionDO> paging = new Paging<>();
//        Integer count = this.baseMapper.allCount(dto.getBeginTime(),dto.getEndTime());
//        paging.setTotal(count.longValue());
//        dto.setStart((dto.getPage() > 0 ? dto.getPage() - 1 : 0) * dto.getLimit());
//        dto.setCount(dto.getLimit());


        List<ChannelActionDO> channelActionDOList =
                this.baseMapper.getChannelActionData(
                        getChannelNoArr(dto.getBeginTime(),dto.getEndTime())
                        ,dto.getBeginTime(),dto.getEndTime());
        paging.setItems(channelActionDOList);
        return paging;
    }

    /**
     * 导出
     * @param beginTime
     * @param endTime
     * @param response
     */
    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public void export(String beginTime, String endTime, HttpServletResponse response) {
        List<ChannelActionDO> channelActionDOList = this.baseMapper.listAll(getChannelNoArr(beginTime,endTime),beginTime,endTime);

        HSSFWorkbook workbook = new HSSFWorkbook();
        //创建一个Excel表单，参数为sheet的名字
        HSSFSheet sheet = workbook.createSheet("订单数据");
        List<String> colList = new ArrayList<>();
        colList.add("渠道编号");
        colList.add("渠道名称");
        colList.add("状态");
        colList.add("创建时间");
        colList.add("结束时间");
        colList.add("访问数量");
        colList.add("访问用户数");
        colList.add("安装量");
        colList.add("注册用户数");
        colList.add("VIP充值次数");
        colList.add("VIP充值人数");
        colList.add("首次VIP充值次数");
        colList.add("7天VIP次数及金额");
        colList.add("30天VIP次数及金额");
        colList.add("90天VIP次数及金额");
        colList.add("180天VIP次数及金额");
        colList.add("365天VIP次数及金额");
        //创建表头
        PoiExcelUtil.setTableHeader(workbook,sheet,colList);

        //新增数据行，并且设置单元格数据
        int rowNum = 1;
        for (ChannelActionDO actionDO: channelActionDOList){
            HSSFRow row = sheet.createRow(rowNum);
            row.createCell(0).setCellValue("000"+actionDO.getChannelId());
            row.createCell(1).setCellValue(actionDO.getChannelName());
            row.createCell(2).setCellValue(actionDO.getChannelStatus() == 1?"生效":"停用");
            row.createCell(3).setCellValue(DateUtil.formatDate(actionDO.getCreateTime(),"yyyy-MM-dd"));
            row.createCell(4).setCellValue(actionDO.getEndTime() == null?"":DateUtil.formatDate(actionDO.getEndTime(),"yyyy-MM-dd"));
            row.createCell(5).setCellValue(actionDO.getPvCount());
            row.createCell(6).setCellValue(actionDO.getUvCount());
            row.createCell(7).setCellValue(actionDO.getDownloadCount());
            row.createCell(8).setCellValue(actionDO.getRegisterCount());
            row.createCell(9).setCellValue(actionDO.getPayCount());
            row.createCell(10).setCellValue(actionDO.getPayUserCount());
            row.createCell(11).setCellValue(actionDO.getPayOneCount());
            row.createCell(12).setCellValue(actionDO.getPackage1()+" / $"+actionDO.getMoney1());
            row.createCell(13).setCellValue(actionDO.getPackage2()+" / $"+actionDO.getMoney2());
            row.createCell(14).setCellValue(actionDO.getPackage3()+" / $"+actionDO.getMoney3());
            row.createCell(15).setCellValue(actionDO.getPackage4()+" / $"+actionDO.getMoney4());
            row.createCell(16).setCellValue(actionDO.getPackage5()+" / $"+actionDO.getMoney5());
            rowNum++;
        }
        String fileName = "channel-data-"+System.currentTimeMillis()+".xls";
        //写入文件并将文件已二进制流的方式返回为调用者
        PoiExcelUtil.writeWorkBook(response,workbook,fileName);
    }

    /**
     * 渠道统计，总量统计
     * @param channelNoArr
     * @return
     */
    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public Object getChannelTotalInfo(String channelNoArr,String options) {
        if (StringUtils.isEmpty(channelNoArr)){
            throw new GunsException(BizExceptionEnum.VPN_CHANNEL_IN_CONDITION_NULL);
        }

        ChannelActionCountDO actionCountDO = this.baseMapper.getChannelActionCount(Arrays.asList(channelNoArr.split(",")),options);
        Integer registerCount = this.baseMapper.getRegisterCount(Arrays.asList(channelNoArr.split(",")),options);

        ChannelTotalStatisticsDO totalDO = new ChannelTotalStatisticsDO();

        totalDO.setRegisterCount(registerCount);
        totalDO.setDownloadCount(actionCountDO.getDownloadCount());
        totalDO.setPvCount(actionCountDO.getPvCount());
        totalDO.setUvCount(actionCountDO.getUvCount());

        return totalDO;
    }

    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public Object getChannelLine(String channelNoArr, String options) {
        if (StringUtils.isEmpty(channelNoArr)){
            throw new GunsException(BizExceptionEnum.VPN_CHANNEL_IN_CONDITION_NULL);
        }
        //查询每日渠道注册信息
        List<ChannelActionInfoOfDailyDO> registrationList =
                this.baseMapper.findChannelRegistrationOfDaily(Arrays.asList(channelNoArr.split(",")),options);

        //查询每日渠道各中事件统计数据
        List<ChannelActionInfoOfDailyDO> pvUvList =
                this.baseMapper.findChannelActionInfoOfDaily(Arrays.asList(channelNoArr.split(",")),options);

        List<ChannelActionInfoOfDailyDO> actionList = new ArrayList<>();
        actionList.addAll(registrationList);
        actionList.addAll(pvUvList);

        ChannelLineBO channelLineBO = new ChannelLineBO();

        Map<Long,ChannelActionInfoOfDailyDO> actionMap = new TreeMap<>(new Comparator<Long>() {
            @Override
            public int compare(Long o1, Long o2) {
                return o1.compareTo(o2);
            }
        });

        actionList.forEach(a->{
            Long timeKey = a.getCreateTime().getTime();
            if (actionMap.get(timeKey) == null){
                actionMap.put(timeKey,a);
            }else{
                ChannelActionInfoOfDailyDO _a = actionMap.get(timeKey);
                _a.setPvCount(_a.getPvCount() + a.getPvCount());
                _a.setUvCount(_a.getUvCount() + a.getUvCount());
                _a.setDownloadCount(_a.getDownloadCount() + a.getDownloadCount());
                _a.setRegisterCount(_a.getRegisterCount() + a.getRegisterCount());
            }
        });

        List<String> dateList = new ArrayList<>();
        List<Integer> registerList = new ArrayList<>();
        List<Integer> downloadList = new ArrayList<>();
        List<Integer> pvList = new ArrayList<>();
        List<Integer> uvList = new ArrayList<>();

        actionMap.forEach((k,c) ->{
            dateList.add(TimeUtil.dateToGTMString(c.getCreateTime(),"yyyy-MM-dd"));
            registerList.add(c.getRegisterCount());
            downloadList.add(c.getDownloadCount());
            pvList.add(c.getPvCount());
            uvList.add(c.getUvCount());
        });

        int len = actionMap.size();

        String[] dateArray = new String[len];
        Integer[] registerArray = new Integer[len];
        Integer[] downloadArray = new Integer[len];
        Integer[] pvArray = new Integer[len];
        Integer[] uvArray = new Integer[len];

        dateList.toArray(dateArray);
        registerList.toArray(registerArray);
        downloadList.toArray(downloadArray);
        pvList.toArray(pvArray);
        uvList.toArray(uvArray);

        channelLineBO.setDateArray(dateArray);
        channelLineBO.setRegisterArray(registerArray);
        channelLineBO.setDownloadArray(downloadArray);
        channelLineBO.setPvArray(pvArray);
        channelLineBO.setUvArray(uvArray);

        return channelLineBO;
    }

    /**
     * 获取漏斗数据
     * @param channelNoArr
     * @param options
     * @return
     */
    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public Object getChannelFunnel(String channelNoArr, String options) {
        if (StringUtils.isEmpty(channelNoArr)){
            throw new GunsException(BizExceptionEnum.VPN_CHANNEL_IN_CONDITION_NULL);
        }

        ChannelActionCountDO actionCountDO = this.baseMapper.getChannelActionCount(Arrays.asList(channelNoArr.split(",")),options);
        Integer registerCount = this.baseMapper.getRegisterCount(Arrays.asList(channelNoArr.split(",")),options);
        Integer paymentCount = this.baseMapper.getPaymentCount(Arrays.asList(channelNoArr.split(",")),options);

        ChannelFunnelDO funnelDO = new ChannelFunnelDO();

        funnelDO.setRegisterCount(registerCount);
        funnelDO.setDownloadCount(actionCountDO.getDownloadCount());
        funnelDO.setPaymentCount(paymentCount);
        funnelDO.setUvCount(actionCountDO.getUvCount());

        return funnelDO;
    }

    /**
     * 查询渠道名称列表
     * @return
     */
    @Override
    @DataSource(name = DatasourceEnum.DATA_SOURCE_BIZ)
    public Object getChannelNames() {
        List<ChannelNameDO> channelNameDOList = this.baseMapper.getChannelNames();
        channelNameDOList.forEach(n ->{
            if (n.getValue().equals("QOEWZ3")){
                n.setSelected(true);
            }
        });
        return channelNameDOList;
    }

    /**
     * 查询某段数据时间间隔内的渠道号数组
     * @param beginTime
     * @param endTime
     * @return
     */
    private List<String> getChannelNoArr(String beginTime,String endTime){
        List<VpnChannelInfo> channelInfoList = new ArrayList<>();

        if (StringUtils.isEmpty(beginTime)
                && StringUtils.isEmpty(endTime)){
            channelInfoList = vpnChannelInfoService.selectList(null);
        }else{
            EntityWrapper<VpnChannelInfo> onWrapper = new EntityWrapper<>();
            onWrapper.eq("status",1);
            List<VpnChannelInfo> onChannelNoList = vpnChannelInfoService.selectList(onWrapper);

            channelInfoList.addAll(onChannelNoList);

            EntityWrapper<VpnChannelInfo> offWrapper = new EntityWrapper<>();
            offWrapper.eq("status",0);
            String bTime = "2020-04-01";
            String eTime = TimeUtil.dateToGTMString(new Date(),"yyyy-MM-dd");
            if (!StringUtils.isEmpty(beginTime)){
                bTime = beginTime;
            }
            if (!StringUtils.isEmpty(endTime)){
                eTime = endTime;
            }

            offWrapper.between("end_time",bTime,eTime);
            List<VpnChannelInfo> offChannelNoList = vpnChannelInfoService.selectList(offWrapper);

            channelInfoList.addAll(offChannelNoList);
        }

        List<String> channelNoArr = new ArrayList<>();

        channelInfoList.forEach(c->{
            channelNoArr.add(c.getChannelNo());
        });
        return channelNoArr;
    }

}
